﻿#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <openssl/rsa.h>
#include <openssl/pem.h>

//#define RSA_PRIVATE_KEY_NAME "kusrpriv.key"
//#define RSA_PUBLIC_KEY_NAME "kusrpub.key"
#define RSA_PRIVATE_KEY_NAME "ksrvpriv.key"
#define RSA_PUBLIC_KEY_NAME "ksrvpub.key"
#define err(fmt, ...) do {err(fmt"\n", ##__VA_ARGS__); } while(0)

enum {
	SUCCESS = 0,
	FAIL = 1
};

int  RSA_Encrypt(char *Source_file, char *Object_file);
int  RSA_Decrypt(char *Source_file, char *Object_file);
RSA  *RSA_read_privatekey(char *Source_file);
RSA  *RSA_read_publickey(char *Source_file);


int main(int argc, char *argv[])
{

    char flag[5];
    char Source_file[32];
    char Object_file[32];

    if(argc != 4)
    {
        printf("nUsage: makeDES <flag> <Source file> <Object file> <key>\n");
        printf("flag        -- 标识，为1时进行加密操作，为2时进行解密操作\n");
        printf("Source file -- 源文件\n");
        printf("Object file -- 目标文件\n");
        return FAIL;
    }

    strcpy(flag,argv[1]);
    strcpy(Source_file,argv[2]);
    strcpy(Object_file,argv[3]);

    if(strcmp(flag, "1") == 0)
    {
        printf("\n您选择的方式是[flag=%s],加密操作\n",flag);
    }
    else
    {
        printf("\n您选择的方式是[flag=%s],解密操作\n",flag);
    }
    printf("Source file: %s\n",Source_file);
    printf("Object file: %s\n",Object_file);

    if(strcmp(flag, "1") == 0)
    {
        RSA_Encrypt(Source_file, Object_file);
    }
    else
    {
        RSA_Decrypt(Source_file, Object_file);
    }

    return SUCCESS;
}

int RSA_Encrypt(char *Source_file, char *Object_file)
{
    FILE *pfPlain, *pfCipher;
    char *PlainBlock, *CipherBlock;
    RSA  *pRsa;
    int  iret = -1, flen, icount = -1, itail = -1;

    if(!(pfPlain = fopen(Source_file, "rb"))) {
        printf ("==============\nopen file [ %s ] error!\n==============\n", Source_file);
        return FAIL;
    }
    if(!(pfCipher = fopen(Object_file, "wb"))) {
        printf ("==============\nopen file [ %s ] error!\n==============\n", Object_file);
        return FAIL;
    }

    pRsa = RSA_new();
   
    pRsa = RSA_read_publickey(RSA_PUBLIC_KEY_NAME);
    pRsa = RSA_read_privatekey(RSA_PRIVATE_KEY_NAME);
    iret = RSA_check_key(pRsa);

    if(iret != 1) {
        printf("key error!\n");
        return FAIL;
    }
   
    flen = RSA_size(pRsa);
    itail = flen - 11;
   
    PlainBlock = (char*)malloc(flen);
    CipherBlock = (char*)malloc(flen);
   
    while(!feof(pfPlain)) {
        if(icount = fread(PlainBlock, sizeof(char), RSA_size(pRsa) - 11, pfPlain)) {
            iret = RSA_public_encrypt(icount, PlainBlock, CipherBlock, pRsa, RSA_PKCS1_PADDING);
            if (iret < 0) {
                printf("Encrypt failed!\n");
                return FAIL;
            }
            fwrite(CipherBlock, sizeof(char), flen, pfCipher);
        }
    }

   
    free(PlainBlock);
    free(CipherBlock);
   
    PlainBlock=NULL;
    CipherBlock=NULL;
   
    fclose(pfPlain);
    fclose(pfCipher);

    RSA_free(pRsa);
   
    printf("RSA_Encrypt OK!\n");
    return SUCCESS;

}

int RSA_Decrypt(char *Source_file, char *Object_file)
{
    FILE            *pfPlain, *pfCipher, *pfkey;
    int             iret, times = 0, flen = 0, icount = -1, itail;
    long            lFileSize;
    unsigned char   *PlainBlock, *CipherBlock;
    char            *key;
    RSA             *pRsa;

    if(!(pfPlain = fopen(Object_file, "wb"))) {
        printf ("==============\nopen file [ %s ] error!\n==============\n", Object_file);
        return FAIL;
    }
    if(!(pfCipher = fopen(Source_file, "rb"))) {
        printf ("==============\nopen file [ %s ] error!\n==============\n", Source_file);
        return FAIL;
    }

    pRsa = RSA_new();
    
    pRsa = RSA_read_privatekey(RSA_PRIVATE_KEY_NAME);

    iret = RSA_check_key(pRsa);
    if(iret != 1) {
        printf("key error!\n");
        return FAIL;
    }
   
    fseek(pfCipher, 0, SEEK_END);      
    lFileSize = ftell(pfCipher);       
    rewind(pfCipher);                  

    flen = RSA_size(pRsa);
    itail = flen - 11;
   
    PlainBlock = (char *)malloc(flen);
    CipherBlock = (char *)malloc(flen);

    printf("RSA_Decrypt begin ......\n");
    while(!feof(pfCipher)) {
        if (icount = fread(CipherBlock, sizeof(char), flen, pfCipher)) {
			iret = RSA_private_decrypt(flen, CipherBlock, PlainBlock, pRsa, RSA_PKCS1_PADDING);
			if(iret < 0) {
				printf("RSA_private_decrypt err!\n");
				return FAIL;
			}
			fwrite(PlainBlock, sizeof(char), iret, pfPlain);
		}
    }

    printf("RSA_Decrypt OK!\n");

    fclose(pfPlain);
    fclose(pfCipher);
    free(PlainBlock);
    free(CipherBlock);
    RSA_free(pRsa);
    return SUCCESS;
}

RSA *RSA_read_privatekey(char *Source_file)
{
    FILE *pfkey;
    RSA  *pRsa;

    if((pfkey = fopen(Source_file, "rb")) == NULL)
    {
        printf ("==============\nopen file [ %s ] error!\n==============\n", Source_file);
        exit(0);
    }

    pRsa = RSA_new();
    pRsa = PEM_read_RSAPrivateKey(pfkey, NULL, NULL, NULL);

    return pRsa;
}

RSA *RSA_read_publickey(char *Source_file)
{
    FILE *pfkey;
    RSA  *pRsa;

    if((pfkey = fopen(Source_file, "rb")) == NULL)
    {
        printf ("==============\nopen file [ %s ] error!\n==============\n", Source_file);
        exit(0);
    }

    pRsa = RSA_new();
    pRsa = PEM_read_RSAPublicKey(pfkey, NULL, NULL, NULL);

    return pRsa;
}